/*
* =====================================================================================
*
*       Filename:  except.h
*
*    Description:  
*
*        Version:  1.0
*        Created:  2010年09月18日 22时57分47秒
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  YOUR NAME (), 
*        Company:  
*
* =====================================================================================
*/
#ifndef EXCEPT_INCLUDE
#define EXCEPT_INCLUDE

#include <setjmp.h>

typedef struct except_s except_t;
struct except_s {
	const char * name;
	const char * description;
};


typedef struct except_frame_s except_frame_t;
struct except_frame_s {
	except_frame_t *prev_frame;
	const char *file;
	unsigned int line;
	except_t *exception;
	jmp_buf env;
};

extern except_frame_t *except_stack;

void except_raise(except_t *e, const char *file, unsigned line);


enum {Except_entered = 0, Except_raised, Except_handled };

#define RAISE(e) except_raise(&(e), __FILE__, __LINE__)
#define RERAISE() do { \
	except_frame_t *p = &(except_frame); \
	except_raise(p->exception, p->file, p->line); \
} while (0) 

#define check_and_clear_frame()  \
		if (except_flag == Except_entered) { \
			except_stack = except_stack->prev_frame;	 \
		} 
	
/* 
* 每条宏语句最终引起的都是一个语法域的开始， 例如 if { ...
* 所以在下一宏语句开始处加上一语句的的结束"}" 以及可能的clean过程
* 
* 比如在TRY语句中，如果需要监控的语句中没有出现异常，那么TRY语句就会
* 正常流动到下一块的开始处，此时必须加上一条弹出本frame的语句
* 但因为不确定到底哪一个语句（是ELSE/EXCEPT/FINALLY）紧接在TRY后面），所以
* 在这些语句前都要加clear过程
* */
#define TRY do { \
	except_frame_t except_frame; \
	except_frame.prev_frame = except_stack; \
	except_stack = &except_frame; \
	volatile int except_flag = setjmp(except_frame.env); \
	if (except_flag == Except_entered) { \
		/*  begin TRY clouse -> */

#define EXCEPT(e)  \
		check_and_clear_frame();	 \
	} else if (except_frame.exception == &(e)) { \
		except_flag = Except_handled; \
		/*  begin EXCEPT clouse -> */
		

/*  ELSE clouse 相当于匹配任意异常,  */
#define ELSE \
		check_and_clear_frame(); \
	} else { \
		except_flag = Except_handled; \
		/*  begin ELSE clouse -> */

#define FINALLY \
		check_and_clear_frame(); \
	} { \
		/*  begin FINALLY clouse -> */

#define ENDTRY  \
		check_and_clear_frame(); \
	} { \
		if (except_flag == Except_raised)  \
			RERAISE(); \
	} \
} while (0);


#endif /* EXCEPT_INCLUDE  */
